package heuristics;

import java.util.LinkedList;
import java.util.List;

import Entities.Calendar;
import Entities.Course;

public class AmbitiousStudentHeuristic implements IHeuristic {
	final static int maxNumberOfCourses = 10;
	final static double averageGradeFactor = 0.5;
	final static double averageGradePenaltyFactor = 0.1;
	final static double workLoadFactor = 0.1;
	final static int maxWorkLoad = 85;
	
	@Override
	public double evaluate(Calendar toEvaluate) {
		double heuristicValue = 0;
		int numberOfCollisions = 0;
		
		if (toEvaluate == null){
			throw new IllegalArgumentException("Illegal calendar to evaluate");
		}
		List<Course> courses = new LinkedList<Course>(toEvaluate.getCourses());
		
		if(!toEvaluate.isEmpty())
		{	// Calendar is not empty
			numberOfCollisions = toEvaluate.getNumberOfCollisions();
			if (numberOfCollisions > 0){
				heuristicValue = (-1)* numberOfCollisions;
			}
			else
			{ // calendar is without collisions
			
				int numberOfCourses = courses.size(); 
				if (numberOfCourses > maxNumberOfCourses){
					heuristicValue -= numberOfCourses;
				}
				
				List<Course> coursesWithoutAdjacents = toEvaluate.getCoursesWithoutAdjacents();
				courses.removeAll(coursesWithoutAdjacents);
				
				// adding course load and grade factors
				for (Course course : courses) {
					heuristicValue += averageGradeFactor*(course.getAverageGrade()*averageGradeNormalizationFactor);
					heuristicValue += workLoadFactor*(Course.MaxWorkLoad - course.getWorkLoad());
				}
				
				for (Course course : coursesWithoutAdjacents) {
					if(course.getAverageGrade() < Calendar.getAverageGrade()) {
						heuristicValue -= averageGradePenaltyFactor*course.getAverageGrade()*averageGradeNormalizationFactor;
					}
				}
				
			}
		}
		return heuristicValue;
	}
	
	@Override
	public int getMaxNumberOfCourses() {
		return maxNumberOfCourses;
	}
	
	public String toString(){
		return "Ambitious Student Heuristic";
	}
}
